package com.crx.springbootinit.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crx.springbootinit.common.WebSocketServer;
import com.crx.springbootinit.exception.ThrowUtils;
import com.crx.springbootinit.mapper.PostMapper;
import com.crx.springbootinit.model.dto.collect.CollectGiveDTO;
import com.crx.springbootinit.model.dto.collect.CollectPageDTO;
import com.crx.springbootinit.model.dto.page.PageVO;
import com.crx.springbootinit.model.entity.Collect;
import com.crx.springbootinit.mapper.CollectMapper;
import com.crx.springbootinit.model.entity.Love;
import com.crx.springbootinit.model.entity.Post;
import com.crx.springbootinit.model.entity.User;
import com.crx.springbootinit.model.vo.collect.CollectMyPostVO;
import com.crx.springbootinit.model.vo.collect.CollectPostListVO;
import com.crx.springbootinit.model.vo.love.LoveMyPostVO;
import com.crx.springbootinit.model.vo.love.LovePostListVO;
import com.crx.springbootinit.model.vo.post.PostHomeVO;
import com.crx.springbootinit.service.ICollectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crx.springbootinit.service.IUserService;
import com.crx.springbootinit.utils.AuthUtils;
import com.crx.springbootinit.utils.ThreadLocalUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.crx.springbootinit.common.ErrorCode.*;

/**
 * <p>
 * 收藏 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-10-21
 */
@Service
@RequiredArgsConstructor
public class CollectServiceImpl extends ServiceImpl<CollectMapper, Collect> implements ICollectService {

    private final RedisTemplate redisTemplate;
    private final PostMapper postMapper;
    private final IUserService userService;



    @Transactional(rollbackFor = Exception.class)
    @Override
    public void giveCollect(CollectGiveDTO collectGiveDTO) {
        //1.判断是收藏还是取消取消收藏
        boolean isCollect= collectGiveDTO.getIsCollect();
        Long postId = collectGiveDTO.getPostId();
        Long userId = collectGiveDTO.getUserId();
        //2.isCollect为true时，收藏，isCollect为false时，取消收藏
        //3.判断用户是否已经收藏过该帖子
        Post post = postMapper.selectById(postId);
        if (post == null) {
            //如果帖子不存在，则提示用户帖子不存在
            ThrowUtils.throwIf(true,OPERATION_ERROR,"帖子不存在");
        }
        if (isCollect) {
            //收藏
            //1.判断用户是否已经收藏过该帖子
            if(isCollect(userId, postId)){
                //2.如果已经收藏过，则提示用户已经收藏过该帖子
                ThrowUtils.throwIf(true,OPERATION_ERROR,"您已经收藏过该帖子");
            }
            //3.如果没有收藏过，则插入收藏数据
            Collect collectPO = BeanUtil.copyProperties(collectGiveDTO, Collect.class);
            Long targetId =post.getUserId();
            if(save(collectPO)){
                try {
                    String nickname = userService.getById(targetId).getNickname();
                    WebSocketServer.sendNotification(targetId,nickname+"收藏了你的帖子");
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            //4.更新post帖子表中的收藏数collectCount(要加上乐观锁)
            LambdaUpdateWrapper<Post> wrapper = new LambdaUpdateWrapper<Post>()
                    .eq(Post::getId, postId)
                    .eq(Post::getCollectCount, post.getCollectCount());
            postMapper.updateGiveCollectCount(wrapper);

        } else {
            //取消收藏
            //1.判断用户是否已经收藏过该帖子
            if(!isCollect(userId, postId)){
                //2.如果没有收藏过，则提示用户没有收藏过该帖子
                ThrowUtils.throwIf(true,OPERATION_ERROR,"您没有收藏过该帖子");
            }
            //3.如果已经收藏过，则删除收藏数据
            remove(new LambdaQueryWrapper<Collect>().eq(Collect::getUserId, userId).eq(Collect::getPostId, postId));
            //4.更新post帖子表中的收藏数collectCount
            LambdaUpdateWrapper<Post> wrapper = new LambdaUpdateWrapper<Post>()
                    .eq(Post::getId, postId)
                    .eq(Post::getCollectCount, post.getCollectCount());
            postMapper.updateCancelCollectCount(wrapper);
        }

    }

    @Override
    public List<CollectMyPostVO> queryWhoCollectMyPostList(String token) {
        //1.从redis中获取用户id(校验非空)
        Long userId= AuthUtils.getUserId(redisTemplate,token);
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<Post>()
                .eq(Post::getUserId, userId);
        List<Post> postList = postMapper.selectList(queryWrapper);
        if(CollUtil.isEmpty(postList)){
            return Collections.emptyList();
        }
        List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());
        //根据帖子的id列表获取收藏列表(非空判断)
        List<Collect> collectList = lambdaQuery().in(Collect::getPostId, postIdList).list();
        if(CollUtil.isEmpty(collectList)){
            return Collections.emptyList();
        }
        //转换成vo列表返回
        List<CollectMyPostVO> collectMyPostVOList = BeanUtil.copyToList(collectList, CollectMyPostVO.class);
        return collectMyPostVOList;
    }

    @Override
    public List<PostHomeVO> queryMyCollectList(Long userId) {
        //1.根据token从redis中获取用户id
//        User user = (User) ThreadLocalUtil.get("user");
//        Long userId= user.getId();
        List<Collect> collectList = lambdaQuery().eq(Collect::getUserId, userId).list();
        if(CollUtil.isEmpty(collectList)){
            return Collections.emptyList();
        }
        List<Long> postIdList = collectList.stream().map(Collect::getPostId).collect(Collectors.toList());
        //3.根据帖子的id列表查询帖子列表
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<Post>()
                .in(Post::getId, postIdList);
        List<Post> postList = postMapper.selectList(queryWrapper);
        List<PostHomeVO> postVOList = new ArrayList<>();
        for (Post record : postList) {
            PostHomeVO postHomeVO = new PostHomeVO();
            BeanUtils.copyProperties(record,postHomeVO);
            String imageListStr = record.getImageList();  // 获取图片列表字符串
            if (imageListStr != null && !imageListStr.isEmpty()) {
                // 使用 Fastjson 解析 JSON 字符串为 List<String>
                List<String> imageList = JSON.parseArray(imageListStr, String.class);
                postHomeVO.setImageList(imageList);  // 设置到 PostHomeVO 中
            }
            JSONArray jsonArray = JSON.parseArray(record.getRoute());
            // 获取第一个和最后一个元素的 name
            if (jsonArray != null && !jsonArray.isEmpty()) {
                // 第一个 name
                JSONObject firstItem = jsonArray.getJSONObject(0);
                String firstName = firstItem.getString("name");

                // 最后一个 name
                JSONObject lastItem = jsonArray.getJSONObject(jsonArray.size() - 1);
                String lastName = lastItem.getString("name");
                postHomeVO.setStartRoute(firstName);
                postHomeVO.setDistance(record.getDistance());
                postHomeVO.setEndRoute(lastName);
            }
            postVOList.add(postHomeVO);
        }
        return postVOList;
    }

    @Override
    public Long getCollectMyCount(String token) {
        //1.根据token从redis中获取用户id
        Long userId= AuthUtils.getUserId(redisTemplate,token);
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<Post>()
                .eq(Post::getUserId, userId);
        List<Post> postList = postMapper.selectList(queryWrapper);
        if(CollUtil.isEmpty(postList)){
            return 0L;
        }
        List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());
        //根据帖子的id列表获取收藏列表(非空判断)
        List<Collect> collectList = lambdaQuery().in(Collect::getPostId, postIdList).list();
        return (long) collectList.size();
    }

    @Override
    public Long getCollectMyCountByUserId(Long userId) {
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<Post>()
                .eq(Post::getUserId, userId);
        List<Post> postList = postMapper.selectList(queryWrapper);
        if(CollUtil.isEmpty(postList)){
            return 0L;
        }
        List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());
        //根据帖子的id列表获取收藏列表(非空判断)
        List<Collect> collectList = lambdaQuery().in(Collect::getPostId, postIdList).list();
        return (long) collectList.size();
    }

    @Override
    public PageVO<CollectMyPostVO> queryCollectPage(CollectPageDTO collectPageDTO) {
        Integer pageNo = collectPageDTO.getPageNo();
        Integer pageSize = collectPageDTO.getPageSize();
        String title = collectPageDTO.getTitle();
        String nickname = collectPageDTO.getNickname();
        Page<Collect> page = new Page<>(pageNo, pageSize);
        Page<Collect> p = lambdaQuery()
                .like(StringUtils.isNotBlank(title), Collect::getTitle, title)
                .like(StringUtils.isNotBlank(nickname), Collect::getNickname, nickname)
                .orderByDesc(Collect::getCreateTime)
                .page(page);
        return PageVO.of(p, CollectMyPostVO.class);
    }
    @Override
    public Boolean isCollect(Long userId, Long postId) {
        boolean exists = lambdaQuery().eq(Collect::getUserId, userId).eq(Collect::getPostId, postId).exists();
        return exists;
    }
}
